﻿using System.Collections.Generic;

namespace ProblemsSet
{
    public class Problem_118 : BaseProblem
    {
        public override object GetResult()
        {
            var tmp = new List<long>();
            FormePrimes(ref tmp, new List<long>(){1,2,3,4,5,6,7,8,9}, 0);
            tmp.Sort();
            var qqq = new List<List<long>>();
            FormeSets(ref qqq, tmp, new List<long>());
            var dct = new Dictionary<long, long>();
            foreach (var list in qqq)
            {
                if (!dct.ContainsKey(list.Count))
                    dct.Add(list.Count, 0);
                dct[list.Count]++;
            }
            long res = 0;
            foreach (var pair in dct)
            {
                res += pair.Value/MathLogic.GetFactorial(pair.Key);
            }
            return res;
        }

        private static void FormeSets(ref List<List<long>> result, List<long> valse, List<long> current)
        {
            foreach (var l in valse)
            {
                var tmp = new List<long>(current);
                tmp.Add(l);
                var q = Compare(tmp);
                if (q.Count == 0) continue;
                if (q.Count == 9)
                {
                    result.Add(tmp);
                    continue;
                }
                var tmp2 = new List<long>();
                var tmp3 = new List<long>();
                for (byte i = 1; i < 10; i++)
                {
                    if (q.Contains(i))
                        continue;
                    tmp3.Add(i);
                }
                FormePrimes(ref tmp2, tmp3, 0);
                FormeSets(ref result, tmp2, tmp);
            }
        }

        private static HashSet<byte> Compare(List<long> value)
        {
            var res = new HashSet<byte>();
            foreach (var l in value)
            {
                var tmp = MathLogic.GetDigitSet(l);
                var s1 = res.Count;
                var s2 = tmp.Count;
                res.UnionWith(tmp);
                if (res.Count != s1 + s2) return new HashSet<byte>();
            }
            return res;
        }

        private static void FormePrimes(ref List<long> result, List<long> vals, long current)
        {
            if (MathLogic.IsPrimeNumber(current))
                result.Add(current);
            foreach (var l in vals)
            {
                var tmp = new List<long>(vals);
                tmp.Remove(l);
                FormePrimes(ref result, tmp, 10*current+l);
            }
        }

        public override string Problem
        {
            get
            {
                return @"Using all of the digits 1 through 9 and concatenating them freely to form decimal integers, different sets can be formed. Interestingly with the set {2,5,47,89,631}, all of the elements belonging to it are prime.

How many distinct sets containing each of the digits one through nine exactly once contain only prime elements?";
            }
        }

        public override bool IsSolved
        {
            get
            {
                return true;
            }
        }

        public override object Answer
        {
            get
            {
                return 44680;
            }
        }

    }
}
